package cn.willbj.brief.hootl.clone.demo;

import java.util.ArrayList;
import java.util.Iterator;

public class Demo01 {
	public static void main(String[] args) throws CloneNotSupportedException {
		Person p = new Demo01().new Person(1, "name01", new Demo01().new Friend(2, new String("name02")));// new StringBuffer("haha")));
		Person p1 = (Person) p.clone();
		p1.name = "new01"; // 看似类似于基本类型，其实暗藏玄机
		p1.age = 10;
		p1.f.name = "new02";
		// p1.f.name = new String("hehe");//新产生了一个引用，覆给了它
		p1.f.age = 20;
		System.out.println(p);// +"—— age"+p.age +" name "+p.name );
		System.out.println(p1);// +"—— age"+p1.age +" name "+p1.name );

		// **************************************************************
		ArrayList testList = new ArrayList();
		testList.add(p);
		testList.add(p1);
		System.out.println("befor testList:" + testList);
		// ArrayList的克隆
		ArrayList newList = (ArrayList) testList.clone();
		// 要一一走访ArrayList/HashMap所指的每一个对象，并逐一克隆。
		for (int i = 0; i < newList.size(); i++)
			newList.set(i, ((Person) newList.get(i)).clone());
		for (Iterator e = newList.iterator(); e.hasNext();)
			((Person) e.next()).age += 1;
		System.out.println("after: testList" + testList);
		System.out.println("after: newList" + newList);
	}

	class Friend implements Cloneable {
		int age;
		String name;// StringBuffer name;

		public Friend(int age, String name) {
			this.age = age;
			this.name = name;
		}

		public Object clone() throws CloneNotSupportedException {
			return super.clone();
		}
	}

	class Person implements Cloneable {
		int age;
		/*
		 * * String 类型特殊，因为他为引用型，而且他指向的值为常量，克隆出来的对象改变他的值
		 * 实际上是改变了克隆出来对象String类型成员的指向，不会影响被克隆对象的值及其指向。
		 */
		String name;
		Friend f;

		public Person(int age, String name, Friend f) {
			this.age = age;
			this.name = name;
			this.f = f;
		}

		// 组合对象的克隆
		public Object clone() throws CloneNotSupportedException {
			Person p = (Person) super.clone(); // 需要对每一个成员对象实现clone()
			p.f = (Friend) p.f.clone();
			return p;
		}

		public String toString() {
			StringBuffer sb = new StringBuffer();
			return super.toString() + sb.append("  age=").append(age).append(",name=").append(name).append("  friend=")
					.append("f.name=").append(f.name).append(",f.age=").append(f.age).toString();
		}
	}
}
